(function(exports) {
	var m = Math,
		floor = m.floor,
		sqrt = m.sqrt,
		atan = m.atan,
		round = m.round,
		ceil = m.ceil;

	exports.Vec2 = function(x, y) {
		this.x = x || 0;
		this.y = y || 0;
	}

	Vec2.prototype = {
		constructor: Vec2,
		add: function(v) {
			return new Vec2(this.x + v.x, this.y + v.y);
		},
		addXY: function(x, y) {
			return new Vec2(this.x + x, this.y + y);
		},
		addX: function(x) {
			return new Vec2(this.x + x, this.y);
		},
		addY: function(y) {
			return new Vec2(this.x, this.y + y);
		},
		sub: function(v) {
			return new Vec2(this.x - v.x, this.y - v.y);
		},
		mul: function(v) {
			return new Vec2(this.x * v.x, this.y * v.y);
		},
		div: function(v) {
			return new Vec2(this.x / v.x, this.y / v.y);
		},
		muSet: function(v) {
			this.x = v.x;
			this.y = v.y;
			return this;
		},
		muAdd: function(v) {
			this.x += v.x;
			this.y += v.y;
			return this;
		},
		muSub: function(v) {
			this.x -= v.x;
			this.y -= v.y;
			return this;
		},
		muMul: function(v) {
			this.x *= v.x;
			this.y *= v.y;
			return this;
		},
		muDiv: function(v) {
			this.x /= v.x;
			this.y /= v.y;
			return this;
		},
		len: function() {
			return sqrt(this.length2());
		},
		len2: function() {
			return this.x * this.x + this.y * this.y;
		},
		dist: function(v) {
			return sqrt(this.dist2(v));
		},
		dist2: function(v) {
			var dx = v.x - this.x;
			var dy = v.y - this.y;
			return dx * dx + dy * dy;
		},
		angle: function() {
			return atan((this.y * this.y) / (this.x * this.x));
		},
		normal: function() {
			var m = sqrt(this.x * this.x + this.y * this.y);
			return new Vec2(this.x / m, this.y / m);
		},
		floor: function() {
			return new Vec2(floor(this.x), floor(this.y));
		},
		round: function() {
			return new Vec2(round(this.x), round(this.y));
		},
		ceil: function() {
			return new Vec2(ceil(this.x), ceil(this.y));
		},
		equals: function(v) {
			return this.x == v.x && this.y == v.y;
		}
	}
})(window);